package org.conann.container

import org.conann.container.examples.*
import org.conann.container.examples.faulty.FaultyClassWithSeveralAnnotatedConstructors
import org.conann.container.examples.faulty.FaultyClassWithSeveralConstructors
import org.conann.exceptions.WebBeansMetadataException
import static org.hamcrest.CoreMatchers.is
import org.junit.Assert
import org.junit.Assume
import org.junit.Test

/** InstanceCreator Tester.   */
public class InstanceCreatorGroovyTest {

    @Test
    public void useDefaultConstructor() {
        Class<ClassWithNoConstructors> type = ClassWithNoConstructors.class;
        Assume.assumeThat type.getDeclaredConstructors().length, is(1)
        Assume.assumeTrue type.getDeclaredConstructors().length == 1;
        Assume.assumeTrue type.getDeclaredConstructors()[0].getParameterTypes().length == 0;

        testCreation(type);
    }

    @Test
    public void useSingleDeclaredConstructor() {
        Class<ClassWithSingleConstructor> type = ClassWithSingleConstructor.class;
        Assume.assumeTrue(type.getDeclaredConstructors().length == 1);

        testCreation(type, "silly value");
    }

    @Test
    public void useConstructorAnnotatedWithInitializer() {
        Class<ClassWithAnnotatedConstructor> type = ClassWithAnnotatedConstructor.class;
        Assume.assumeTrue(type.getDeclaredConstructors().length > 1);

        testCreation(type, "silly value");
    }

    @Test
    public void useConstructorWithBindingAnnotetationsParams() {
        Class<ClassWithConstructorWithAnnotatedParams> type = ClassWithConstructorWithAnnotatedParams.class;
        // TODO ophir >> declare the type assumptions
        testCreation(type, "silly value");
    }

    @Test (expected = WebBeansMetadataException.class)
    public void faultyClassWithSeveralConstructors() {
        final Class<FaultyClassWithSeveralConstructors> type = FaultyClassWithSeveralConstructors.class;
        getType().getDeclaredConstructors().every {it.get}
        Assume.assumeTrue(type.getDeclaredConstructors().length > 1);
        // TODO ophir >> declare the type assumptions
        testCreation(type);
    }

    @Test (expected = WebBeansMetadataException.class)
    public void faultyClassWithSeveralAnnotatedConstructors() {
        Class<FaultyClassWithSeveralAnnotatedConstructors> type = FaultyClassWithSeveralAnnotatedConstructors.class;
        // TODO ophir >> declare the type assumptions
        testCreation(type);
    }

    private <T extends BaseClassForConstruction> T testCreation(Class<T> type, Object ... instantiationParams) {
        InstanceCreator<T> creator = new InstanceCreator<T>(type);
        Assert.assertNotNull(creator);
        T instance = creator.instantiate(instantiationParams);
        Assert.assertNotNull(instance);
        Assert.assertTrue(instance.isProperlyConstructed());
        return instance;
    }
}